#include "MsgInstanceClient.h"



CMsgInstanceClient :: CMsgInstanceClient(char *addr, int port, int skeepalive)
{
   eventList.clear();
   m_fd = -1;
   m_skeepalive = skeepalive;
   m_validlen = 0;
   m_Communi = new CCommunication();
   if((m_Communi->SocketIntanceTCP(SOCKET_CLIENT, NULL, 0)) >= 0)
    {
       if(m_Communi->SocketConnect(addr, port) >= 0 )
       {
            COMLOG_ERROR_LOG("connect server successed\n");
            m_fd = m_Communi->SocketFdGet();
       } 
       else
            COMLOG_ERROR_LOG("connect server error\n");
    }
    else
    {
         COMLOG_ERROR_LOG("connect server error\n");
    }
    memset(m_readbuf, 0, sizeof(m_readbuf));
    memset(m_addr, 0, sizeof(m_addr));
    memcpy(m_addr, addr, strlen(addr));
    m_port = port;
    lastKeepaliveTime = 0;
}



CMsgInstanceClient :: ~CMsgInstanceClient()
{
    m_Communi->SocketClose(m_fd);
    
   //  for(auto it = eventList.begin(); it != eventList.end(); it++)
   //  {
   //      for(auto iti = it->second.begin(); iti !=  it->second.end(); iti++)
   //      {
   //               free(iti->second.data);
   //               iti->second.data = NULL;

   //      }

   //  }
    eventList.clear();
    delete m_Communi;
}


      
int CMsgInstanceClient :: MsgEventRegister(int msgSource, eEVENTID event, ...)
{
   va_list vl;
   va_start(vl, event);
   CNullClass *thisp = va_arg(vl, CNullClass*);
   CallbackFunc func = va_arg(vl, CallbackFunc);
   void *data = va_arg(vl, void *);
   va_end(vl);
   CBEvent cbtemp = {0};
   cbtemp.thisp = thisp;
   cbtemp.func = func;
   cbtemp.data = data;
   eventList[event][msgSource] = cbtemp;

   int totalLen = MSG_PACK_LEN + 2;
   MsgPacket *msgPacket = ( MsgPacket *)malloc(totalLen);
   msgPacket->len = 0; 
   msgPacket->event = event;
   memcpy(msgPacket->header, "HEAD", 4);;
   msgPacket->msgtype = SUBSCRIBE;
   msgPacket->data[0] = 0xaa;
   msgPacket->data[1] = 0x55;
   m_Communi->SocketWrite((char *)msgPacket, totalLen);
   free(msgPacket);
   msgPacket = NULL;
   return 0 ;
}

void CMsgInstanceClient :: MsgRegisterEventDataWrite(eEVENTID event)
{
   int totalLen = MSG_PACK_LEN + 2;
   MsgPacket *msgPacket = ( MsgPacket *)malloc(totalLen);
   msgPacket->len = 0; 
   msgPacket->event = event;
   memcpy(msgPacket->header, "HEAD", 4);;
   msgPacket->msgtype = SUBSCRIBE;
   msgPacket->data[0] = 0xaa;
   msgPacket->data[1] = 0x55;
   m_Communi->SocketWrite((char *)msgPacket, totalLen);
   free(msgPacket);
   msgPacket = NULL;
   return;
}


int CMsgInstanceClient :: MsgEventUnRegister(int msgSource, eEVENTID event)
{
   if(eventList[event].find(msgSource) != eventList[event].end())
   {
      eventList[event].erase(eventList[event].find(msgSource));
      int totalLen = MSG_PACK_LEN + 2;
      MsgPacket *msgPacket = ( MsgPacket *)malloc(totalLen);
      msgPacket->len = 0; 
      msgPacket->event = event;
      memcpy(msgPacket->header, "HEAD", 4);;
      msgPacket->msgtype = UNSUBSCRIBE;
      msgPacket->data[0] = 0xaa;
      msgPacket->data[1] = 0x55;
      m_Communi->SocketWrite((char *)msgPacket, totalLen);
      free(msgPacket);
      msgPacket = NULL;

   }   
   return 0;
}

int CMsgInstanceClient :: MsgPublish(eEVENTID event, void *data, int datalen, char needresponse)
{
   int totalLen = sizeof(MsgPacket) +  datalen + 2;
   MsgPacket *msgPacket = (MsgPacket *)malloc(totalLen);
   memcpy(msgPacket->data, data, datalen);
   msgPacket->len = datalen;
   memcpy(msgPacket->header, "HEAD", 4);
   msgPacket->event = event;
   msgPacket->msgtype = needresponse == 1 ? PUBRESPONSE : PUBLISH;
   msgPacket->data[datalen] = 0xaa;
   msgPacket->data[datalen + 1] = 0x55;
   m_Communi->SocketWrite((char *)msgPacket, totalLen);
   free(msgPacket);
   msgPacket = NULL;
   return 0;
}

int CMsgInstanceClient :: MsgSchedule()
{
   time_t curKeepaliveTime = time(NULL);
   int ret = 0;
   MsgPacket *tempMsg = NULL ;
   int datalen = 0;
   //间隔一段时间发送心跳包
   if(curKeepaliveTime - lastKeepaliveTime >= m_skeepalive)
   {
      lastKeepaliveTime = curKeepaliveTime;
      MsgSendHeartPack();
   }
   //读取网络数据,并进行解析交互包
   if((ret = m_Communi->SocketRead(m_fd, m_readbuf + m_validlen, sizeof(m_readbuf), 30)) > 0)
   {
      m_validlen += ret;
      while(m_validlen > 0)
      {
         if(m_validlen >= MSG_PACK_LEN + 2)
         {
            //解包
            if(0 == memcmp(m_readbuf, "HEAD", 4)) 
            {
               COMLOG_DEBUG_HEXDUMP(m_readbuf, m_validlen);
               datalen = CONVERT_CAHR_TO_INT(m_readbuf[4], m_readbuf[5], m_readbuf[6], m_readbuf[7]);
               COMLOG_DEBUG_LOG("find pack head and data len is %d\n", datalen);
               if(m_validlen < datalen + MSG_PACK_LEN + 2)
               {
                  return 0;
               }
               else if(m_readbuf[datalen + MSG_PACK_LEN] != (char)0xaa || m_readbuf[datalen + MSG_PACK_LEN + 1] != (char)0x55)
               {
                  COMLOG_ERROR_LOG("end check is error %d %02x %02x\n", MSG_PACK_LEN, m_readbuf[datalen + MSG_PACK_LEN], m_readbuf[datalen + MSG_PACK_LEN + 1]);
                  memmove(m_readbuf , m_readbuf + datalen + MSG_PACK_LEN + 2, m_validlen - datalen - MSG_PACK_LEN - 2);
                  m_validlen -= (datalen + MSG_PACK_LEN + 2);
                  return 0;
               }
            }
            else
            {
               COMLOG_DEBUG_LOG("no find pack head\n");
               memmove(m_readbuf, m_readbuf+4, m_validlen - 4);
               m_validlen -= 4;   
               return 0;
            }
            //填充结构体
            COMLOG_DEBUG_LOG("start analyse pack data\n");
            if((tempMsg = MsgConvertByteToMsgpacket(m_readbuf, datalen + MSG_PACK_LEN + 2)) != NULL) 
            {
                  COMLOG_DEBUG_LOG("end analyse pack data, start distribute pack data\n");
                  MsgDistributePack(tempMsg);
                  free(tempMsg);
                  tempMsg = NULL;
            }
            //移动数据
            memmove(m_readbuf , m_readbuf + datalen + MSG_PACK_LEN + 2, m_validlen - datalen - MSG_PACK_LEN - 2);
            m_validlen -= (datalen + MSG_PACK_LEN + 2);
         }
         else
         {
            COMLOG_ERROR_LOG("data is not enough, lower pack header\n");
            break;
         }

      }
   }
   else if(SOCKETDOWN == ret)
   {
      COMLOG_ERROR_LOG("connect server down\n");
      m_Communi->SocketClose(m_fd);
      if((m_Communi->SocketIntanceTCP(SOCKET_CLIENT, NULL, 0)) >= 0)
      {
         if(m_Communi->SocketConnect(m_addr, m_port) >= 0 )
         {
               COMLOG_INFO_LOG("reconnect server successed\n");
               m_fd = m_Communi->SocketFdGet();
         } 
      }
      //重新注册事件
      for(auto it  = eventList.begin(); it != eventList.end(); it++)
      {
         MsgRegisterEventDataWrite((eEVENTID)it->first);
      }
   }
   return 0;
}

void CMsgInstanceClient :: PrinteventList()
{
   for(auto i  = eventList.begin(); i != eventList.end(); i++)
   {

     printf("event id:%d\n", i->first);
     for(auto j = i->second.begin(); j != i->second.end(); j++)
     {

        printf("source id:%d\n", j->first);
        CNullClass * p =  j->second.thisp;
        CallbackFunc func = j->second.func;
        (p->*func)("dsadsa", 11, NULL);
     }
        

   }
}

void CMsgInstanceClient :: MsgSendHeartPack()
{
   int totalLen = MSG_PACK_LEN + 2;
   MsgPacket *msgPacket = (MsgPacket *)malloc(totalLen);
   msgPacket->len = 0;
   memcpy(msgPacket->header, "HEAD", 4);
   msgPacket->event = KEEPALIVE_EVENT;
   msgPacket->msgtype = PUBLISH;
   msgPacket->data[0] = 0xaa;
   msgPacket->data[1] = 0x55;
   m_Communi->SocketWrite((char *)msgPacket, totalLen);
   free(msgPacket);
   COMLOG_ERROR_LOG("client %d send heart pack\n", m_fd);
   msgPacket = NULL;
}


MsgPacket * CMsgInstanceClient :: MsgConvertByteToMsgpacket(char *data, int datalen)
{
     MsgPacket *tempMsg = (MsgPacket *)malloc(datalen);
     memcpy(tempMsg, data, datalen);
     return tempMsg;
}



void CMsgInstanceClient :: MsgDistributePack(MsgPacket *msgPacket)
{
     if(NULL == msgPacket)
     {
         COMLOG_ERROR_LOG("msgPacket is NULL\n");
         return ;
     }
     auto it = eventList.find(msgPacket->event);
     if(it == eventList.end())
     {
          COMLOG_ERROR_LOG("no find valid event\n");
          return;
     }
     for(auto iti = it->second.begin(); iti != it->second.end(); iti++)
      {
         CNullClass *thisp = iti->second.thisp;
         CallbackFunc cb  = iti->second.func;
         void *data = iti->second.data;
         (thisp->*cb)((char *)msgPacket, msgPacket->len + 2 + MSG_PACK_LEN, data);

      }
}



void CMsgInstanceClient :: TestEventCB(char *msg, int msgLen, void *data)
{
      MsgPacket *msgPacket = (MsgPacket *)msg;
      COMLOG_ERROR_LOG("event:%d \n", msgPacket->event);
      COMLOG_DEBUG_HEXDUMP(msg, msgLen);


}